package com.edu.exam.entity.curriculum.questionbank;

import com.edu.exam.enums.curriculum.questionbank.SyncTaskStatus;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;

import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.time.LocalDateTime;

/**
 * 同步任务实体类
 * 对应数据库表：sync_tasks
 *
 * 管理属性同步任务，包括任务类型、状态、进度等。
 * 支持同步任务的创建、查询、更新和状态管理。
 * 提供完整的任务生命周期管理，确保属性数据的同步一致性。
 *
 * @author System
 * @version 1.0.0
 */
@Entity
@Comment("同步任务表")
@SQLDelete(sql = "UPDATE sync_tasks SET is_deleted = true, delete_time = CURRENT_TIMESTAMP WHERE id = ?")
@Where(clause = "is_deleted = false")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class SyncTask {

    /**
     * 任务唯一标识符
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /**
     * 同步类型
     */
    @NotBlank(message = "同步类型不能为空")
    @Enumerated(EnumType.STRING)
    @Column(name = "sync_type", nullable = false, length = 50)
    private SyncType syncType;

    /**
     * 任务状态
     */
    @NotNull(message = "任务状态不能为空")
    @Enumerated(EnumType.STRING)
    @Column(name = "status", nullable = false, length = 20)
    @Builder.Default
    private SyncTaskStatus status = SyncTaskStatus.PENDING;

    /**
     * 任务优先级
     */
    @NotNull(message = "任务优先级不能为空")
    @Enumerated(EnumType.STRING)
    @Column(name = "priority", nullable = false, length = 20)
    @Builder.Default
    private TaskPriority priority = TaskPriority.NORMAL;

    /**
     * 总模块数
     */
    @NotNull(message = "总模块数不能为空")
    @Column(name = "total_modules", nullable = false)
    @Builder.Default
    private Integer totalModules = 0;

    /**
     * 已完成模块数
     */
    @NotNull(message = "已完成模块数不能为空")
    @Column(name = "completed_modules", nullable = false)
    @Builder.Default
    private Integer completedModules = 0;

    /**
     * 失败模块数
     */
    @NotNull(message = "失败模块数不能为空")
    @Column(name = "failed_modules", nullable = false)
    @Builder.Default
    private Integer failedModules = 0;

    /**
     * 任务标题
     */
    @NotBlank(message = "任务标题不能为空")
    @Size(max = 200, message = "任务标题长度不能超过200个字符")
    @Column(name = "title", nullable = false, length = 200)
    private String title;

    /**
     * 任务描述
     */
    @Size(max = 1000, message = "任务描述长度不能超过1000个字符")
    @Column(name = "description", columnDefinition = "TEXT")
    private String description;

    /**
     * 任务参数，JSON格式
     */
    @Column(name = "parameters", columnDefinition = "TEXT")
    private String parameters;

    /**
     * 任务结果，JSON格式
     */
    @Column(name = "result", columnDefinition = "TEXT")
    private String result;

    /**
     * 错误信息
     */
    @Column(name = "error_message", columnDefinition = "TEXT")
    private String errorMessage;

    /**
     * 开始时间
     */
    @Column(name = "start_time")
    private LocalDateTime startTime;

    /**
     * 完成时间
     */
    @Column(name = "complete_time")
    private LocalDateTime completeTime;

    /**
     * 预计完成时间
     */
    @Column(name = "estimated_completion_time")
    private LocalDateTime estimatedCompletionTime;

    /**
     * 超时时间（分钟）
     */
    @Column(name = "timeout_minutes")
    @Builder.Default
    private Integer timeoutMinutes = 60;

    /**
     * 重试次数
     */
    @Column(name = "retry_count")
    @Builder.Default
    private Integer retryCount = 0;

    /**
     * 最大重试次数
     */
    @Column(name = "max_retry_count")
    @Builder.Default
    private Integer maxRetryCount = 3;

    /**
     * 任务进度百分比
     */
    @Column(name = "progress_percentage")
    @Builder.Default
    private Integer progressPercentage = 0;

    /**
     * 乐观锁版本号
     */
    @Version
    @Column(name = "version", nullable = false)
    @Builder.Default
    private Integer version = 1;

    /**
     * 软删除标记
     */
    @Column(name = "is_deleted", nullable = false)
    @Builder.Default
    private Boolean isDeleted = false;

    /**
     * 删除时间
     */
    @Column(name = "delete_time")
    private LocalDateTime deleteTime;

    /**
     * 创建人用户ID
     */
    @Size(max = 50, message = "创建人长度不能超过50个字符")
    @Column(name = "created_by", nullable = false, length = 50)
    private String createdBy;

    /**
     * 记录创建时间
     */
    @Column(name = "created_time", nullable = false, updatable = false)
    private LocalDateTime createdTime;

    /**
     * 最后更新人用户ID
     */
    @Size(max = 50, message = "更新人长度不能超过50个字符")
    @Column(name = "updated_by", length = 50)
    private String updatedBy;

    /**
     * 记录最后更新时间
     */
    @Column(name = "updated_time", nullable = false)
    private LocalDateTime updatedTime;

    @PrePersist
    protected void onCreate() {
        LocalDateTime now = LocalDateTime.now();
        this.createdTime = now;
        this.updatedTime = now;
    }

    @PreUpdate
    protected void onUpdate() {
        this.updatedTime = LocalDateTime.now();
    }

    /**
     * 同步类型枚举
     */
    public enum SyncType {
        ATTRIBUTE_SYNC("ATTRIBUTE_SYNC", "属性同步"),
        CATEGORY_SYNC("CATEGORY_SYNC", "分类同步"),
        TAG_SYNC("TAG_SYNC", "标签同步"),
        DIFFICULTY_SYNC("DIFFICULTY_SYNC", "难度同步"),
        VALIDATION_SYNC("VALIDATION_SYNC", "验证规则同步"),
        FULL_SYNC("FULL_SYNC", "全量同步"),
        INCREMENTAL_SYNC("INCREMENTAL_SYNC", "增量同步");

        private final String code;
        private final String description;

        SyncType(String code, String description) {
            this.code = code;
            this.description = description;
        }

        public String getCode() {
            return code;
        }

        public String getDescription() {
            return description;
        }

        public static SyncType fromCode(String code) {
            for (SyncType type : values()) {
                if (type.getCode().equals(code)) {
                    return type;
                }
            }
            return ATTRIBUTE_SYNC;
        }
    }

    /**
     * 任务优先级枚举
     */
    public enum TaskPriority {
        LOW("LOW", "低"),
        NORMAL("NORMAL", "普通"),
        HIGH("HIGH", "高"),
        URGENT("URGENT", "紧急");

        private final String code;
        private final String description;

        TaskPriority(String code, String description) {
            this.code = code;
            this.description = description;
        }

        public String getCode() {
            return code;
        }

        public String getDescription() {
            return description;
        }

        public static TaskPriority fromCode(String code) {
            for (TaskPriority priority : values()) {
                if (priority.getCode().equals(code)) {
                    return priority;
                }
            }
            return NORMAL;
        }
    }
}